package org.jackysoft.util;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.jackysoft.entity.HibernateStep;
import org.jackysoft.entity.Step;
import org.jackysoft.entity.Variable;
import org.jackysoft.opensymphony.workflow.entity.ActionDescriptor;
import org.jackysoft.opensymphony.workflow.entity.JoinDescriptor;
import org.jackysoft.opensymphony.workflow.entity.ResultDescriptor;
import org.jackysoft.opensymphony.workflow.entity.SplitDescriptor;
import org.jackysoft.opensymphony.workflow.entity.StepDescriptor;
import org.jackysoft.opensymphony.workflow.entity.WorkflowDescriptor;
import org.joda.time.DateTime;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public final class WorkflowUtil {
     public static String getStepName(long stepId){
    	 return null;
     }
     public static String getVarStringValue(Variable var){
 		if(var==null)return null;
 		return var.getValue();
 	}
     
     public static DateTime getVarDateValue(Variable var){
     	if(var==null)return null;
     	return var.getDateTime();
     }
     
     public static String getVarStringValue(Long entityId,String var){
     	
     	return null;
     }
     
     
     public static Set<String> getWorkflowNames() {
 		ClassLoader loader = Thread.currentThread().getContextClassLoader();
 		InputStream input = loader.getResourceAsStream("workflows.xml");
 		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
 		Set<String> workflowNames = new HashSet<String>();
 		try {
 			DocumentBuilder builder = factory.newDocumentBuilder();
 			builder.setEntityResolver(new IgnoreDtdValidateResolver());
 			Document doc = builder.parse(input);
 			Element root = doc.getDocumentElement();
 			NodeList children = root.getChildNodes();
 			for (int i = 0; i < children.getLength(); i++) {
 				Node child = children.item(i);
 				if (child instanceof Element) {
 					Element element = (Element) child;
 					if ("workflow".equals(element.getTagName())) {
 						workflowNames.add(element.getAttribute("name"));
 					}

 				}
 			}
 		} catch (ParserConfigurationException e) {

 			e.printStackTrace();
 		} catch (SAXException e) {

 			e.printStackTrace();
 		} catch (IOException e) {

 			e.printStackTrace();
 		}
 		return workflowNames;
 	}

 	public static Map<String, String> getAviliableWorkflowMap() {
 		ClassLoader loader = Thread.currentThread().getContextClassLoader();
 		InputStream input = loader.getResourceAsStream("workflows.xml");
 		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
 		Map<String, String> workflownames = new HashMap<String, String>();
 		try {
 			DocumentBuilder builder = factory.newDocumentBuilder();
 			builder.setEntityResolver(new IgnoreDtdValidateResolver());
 			Document doc = builder.parse(input);
 			Element root = doc.getDocumentElement();
 			NodeList children = root.getChildNodes();
 			for (int i = 0; i < children.getLength(); i++) {
 				Node child = children.item(i);
 				if (child instanceof Element) {
 					Element element = (Element) child;
 					if ("workflow".equals(element.getTagName())) {
 						workflownames.put(element.getAttribute("name"), element
 								.getAttribute("location"));
 					}

 				}
 			}
 		} catch (ParserConfigurationException e) {
 			// TODO 自动生成 catch 块
 			e.printStackTrace();
 		} catch (SAXException e) {
 			// TODO 自动生成 catch 块
 			e.printStackTrace();
 		} catch (IOException e) {
 			// TODO 自动生成 catch 块
 			e.printStackTrace();
 		}
 		return workflownames;
 	}

 	/**
 	 * @param workflowname
 	 *            工作流名称
 	 * @return id-name 值对Map
 	 */
 	public static Map<String, String> getStepIdNameMap(String workflowname) {
 		ClassLoader loader = Thread.currentThread().getContextClassLoader();
 		Map<String, String> workflows = getAviliableWorkflowMap();
 		String location = workflows.get(workflowname);
 		InputStream input = loader.getResourceAsStream(location);
 		final Map<String, String> steps = new HashMap<String, String>();
 		SAXParserFactory factory = SAXParserFactory.newInstance();
 		try {

 			factory
 					.setFeature(
 							"http://apache.org/xml/features/nonvalidating/load-external-dtd",
 							false);
 			factory.setFeature("http://xml.org/sax/features/validation", false);
 			SAXParser parser = factory.newSAXParser();

 			parser.parse(input, new DefaultHandler() {

 				@Override
 				public void startElement(String uri, String localName,
 						String qName, Attributes attributes)
 						throws SAXException {
 					if ("step".equalsIgnoreCase(qName) && attributes != null) {
 						String id = attributes.getValue("id");
 						String sname = attributes.getValue("name");
 						steps.put(id, sname);
 					}
 				}

 			});
 		} catch (ParserConfigurationException e) {
 			// TODO 自动生成 catch 块
 			e.printStackTrace();
 		} catch (SAXException e) {
 			// TODO 自动生成 catch 块
 			e.printStackTrace();
 		} catch (IOException e) {
 			// TODO 自动生成 catch 块
 			e.printStackTrace();
 		}

 		return steps;
 	}

 	public static SortedMap<Integer, String> getStepInfomation(
 			WorkflowDescriptor wdes) {
 		final SortedMap<Integer, String> steps = new TreeMap<Integer, String>(
 				new Comparator<Integer>() {

 					@Override
 					public int compare(Integer o1, Integer o2) {
 						if (o1 > o2)
 							return 1;
 						else if (o1 == o2)
 							return 0;
 						else
 							return -1;

 					}

 				});
 		for (Object o : wdes.getSteps()) {
 			StepDescriptor step = (StepDescriptor) o;
 			steps.put(new Integer(step.getId()), step.getName());
 		}

 		return steps;
 	}

 	/**
 	 * 功能:根据actionId 获取action 定义所在 的Step id
 	 * 
 	 * @param workflow
 	 *            工作流对象
 	 * @param actionId
 	 *            活动编号
 	 * @param workflowId
 	 *            工作流编号
 	 * @return 步骤Id
 	 */
 	public static Step getStepIdByActionId(WorkflowDescriptor descriptor,
 			int actionId, long workflowId, List csteps) {
 		Step tstep = null;
 		// 遍历当前步骤 找出与包含活动参数相等的步骤
 		outer: for (Object so : csteps) {
 			Step step = (HibernateStep) so;
 			StepDescriptor sdesc = descriptor.getStep(step.getStepId());
 			List actions = sdesc.getActions();
 			for (Object adesc : actions) {
 				ActionDescriptor asc = (ActionDescriptor) adesc;
 				if (asc.getId() == actionId) {
 					tstep = step;
 					break outer;
 				}
 			}
 		}
 		return tstep;
 	}

 	/**
 	 * 功能:根据actionId 获得 该action 的下步List<StepDescriptor>
 	 * 
 	 * @param workflow
 	 *            工作流对象
 	 * @param actionId
 	 *            活动编号
 	 * @param workflowId
 	 *            工作流编号
 	 * @return 步骤描述列表list;
 	 */

 	@SuppressWarnings("unchecked")
 	public static List<StepDescriptor> getNextSteps(
 			WorkflowDescriptor descriptor, long workflowId, int actionId) {
 		List<StepDescriptor> nextSteps = new ArrayList<StepDescriptor>();
 		ActionDescriptor adesc = descriptor.getAction(actionId);
 		ResultDescriptor uresult = adesc.getUnconditionalResult();
 		List cresults = adesc.getConditionalResults();
 		nextSteps.addAll(parseStep(descriptor, uresult));
 		nextSteps.addAll(parseStep(descriptor, cresults));

 		return nextSteps;
 	}

 	/**
 	 * 
 	 */
 	private static List<StepDescriptor> parseStep(
 			WorkflowDescriptor descriptor, ResultDescriptor results) {
 		List<StepDescriptor> nextSteps = new ArrayList<StepDescriptor>();
 		if (null == results)
 			return nextSteps;
 		else {
 			if (results.getStep() != 0) {
 				nextSteps.add(descriptor.getStep(results.getStep()));
 				return nextSteps;
 			} else if (results.getJoin() != 0) {
 				JoinDescriptor jdesc = descriptor.getJoin(results.getJoin());
 				ResultDescriptor trs = jdesc.getResult();
 				nextSteps.add(descriptor.getStep(trs.getStep()));
 				return nextSteps;
 			} else if (results.getSplit() != 0) {
 				SplitDescriptor sdesc = descriptor.getSplit(results.getSplit());
 				List trs = sdesc.getResults();
 				for (Object o : trs) {
 					ResultDescriptor rd = (ResultDescriptor) o;
 					nextSteps.add(descriptor.getStep(rd.getStep()));
 				}
 				return nextSteps;
 			}
 		}
 		return nextSteps;
 	}

 	private static List<StepDescriptor> parseStep(
 			WorkflowDescriptor descriptor, List<ResultDescriptor> results) {
 		List<StepDescriptor> nextSteps = new ArrayList<StepDescriptor>();
 		if (null == results)
 			return nextSteps;
 		else {
 			for (ResultDescriptor result : results)
 				nextSteps.addAll(parseStep(descriptor, result));

 		}
 		return nextSteps;
 	}
}
